﻿using Autofac;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Shared.AutofacHelper
{
    public static class AutofacContainerBuilder
    {
        /// <summary>
        /// 查找bin文件夹下的所有DLL,进行注册
        /// </summary>
        /// <returns></returns>
        private static IEnumerable<Assembly> GetAssemblies()
        {
            List<Assembly> assemblies = new List<Assembly>();
            try
            {
                string[] files = Directory.GetFiles(AppContext.BaseDirectory, "*.dll");//得到文件
                foreach (string file in files)//循环文件
                {
                    try
                    {
                        //防止非 .net DLL 加载引发异常
                        //目前没有找到好方法进行判断是否是.net程序集,姑且先用try进行处理

                        //因为添加 7z.DLL 的使用所以此处出问题 
                        var assembly = Assembly.LoadFrom(file);
                        assemblies.Add(assembly);
                    }
                    catch (Exception ex)
                    { }
                }
            }
            catch (Exception ex)
            { }
            return assemblies;
        }
        /// <summary>
        /// Autofac 注册
        /// </summary>
        /// <param name="mvcControllerAssembly">
        /// 包含当前MVC执行的代码的程序集,
        /// 通过 Assembly.GetExecutingAssembly() 获取
        /// </param>
        public static void RegisterAssembly(this ContainerBuilder containerBuilder, Lifetime lifetime = 0)
        {
            Type baseType = typeof(Shared.Contracts.IDependency);// typeof(IDependency);
            Assembly[] assemblies = GetAssemblies().ToArray();

            var IRegistrationBuilder = containerBuilder.RegisterAssemblyTypes(assemblies)
                 .Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface)
                 //.EnableInterfaceInterceptors() //启用接口的拦截器[AOP]
                 //.InterceptedBy(typeof(MethodInterceptor)) //拦截类型为MethodInterceptor[AOP]
                 .AsImplementedInterfaces();

            switch (lifetime)
            {
                case Lifetime.InstancePerDependency:
                    IRegistrationBuilder.InstancePerLifetimeScope();
                    break;
                case Lifetime.SingleInstance:
                    IRegistrationBuilder.SingleInstance();
                    break;
                case Lifetime.InstancePerLifetimeScope:
                    IRegistrationBuilder.InstancePerLifetimeScope();
                    break;
                case Lifetime.InstancePerMatchingLifetimeScope:
                    IRegistrationBuilder.InstancePerMatchingLifetimeScope();
                    break;
                case Lifetime.InstancePerRequest:
                    IRegistrationBuilder.InstancePerRequest();
                    break;
                case Lifetime.InstancePerOwned:
                    //IRegistrationBuilder.InstancePerOwned();
                    break;
            }
        }
    }
    /// <summary>
    /// 详细可以参考
    /// https://www.cnblogs.com/stulzq/p/8547277.html
    /// </summary>
    public enum Lifetime
    {
        /// <summary>
        /// 返回一个新的实例，并且这是默认的生命周期。
        /// </summary>
        InstancePerDependency = 0,
        /// <summary>
        /// 单例，所有服务请求都将会返回同一个实例。
        /// </summary>
        SingleInstance = 1,
        /// <summary>
        /// 在一个嵌套语句块中，只会返回一个实例
        /// 在解决每个生命周期实例作用域组件时，每个嵌套作用域将获得一个实例（例如，每个工作单元）。
        /// </summary>
        InstancePerLifetimeScope = 2,
        /// <summary>
        /// 每个生命周期的实例范围'概念类似，但允许更精确地控制实例共享
        /// </summary>
        InstancePerMatchingLifetimeScope = 3,
        /// <summary>
        /// 某些应用程序类型自然适用于“请求”类型语义，例如ASP.NET Web Forms和MVC应用程序。 
        /// 在这些应用程序类型中，有能力为每个请求提供一种“单例”
        /// </summary>
        InstancePerRequest = 4,
        /// <summary>
        /// 拥有的隐式关系类型创建新的嵌套生命周期作用域。 可以使用每个拥有实例的注册来将依赖关系限定到拥有的实例。
        /// </summary>
        InstancePerOwned = 5,
    }
}
